require 'paint'
require 'fileutils'
require 'erb'

# Public: Hash of colored and aligned Strings for displaying command actions.
# If interpolated, don't use any surrounding spaces.
LABELS = {
  add:       Paint['        add  ', :green],
  ignore:    Paint['     ignore  ', :blue],
  overwrite: Paint['  overwrite  ', :yellow],
  remove:    Paint['     remove  ', :red],
  run:       Paint['        run  ', :magenta]
}

# Public: String path location of the templates directory.
TEMPLATES = "#{File.dirname(__FILE__)}/../templates"

# Public: Asks the user if a file should be overwritten.
# 
# file - Sting path of file in question
# 
# Example
# 
#   overwritable? 'path/to/my/file.rb'
# 
# Returns true or false based on user selection.
def overwritable? path
  puts "#{path} already exists. Replace? (yes or no)"
  decision = gets.strip!.downcase!
  return false unless (decision == 'yes') || (decision == 'y')
  return true
end

# Public: Adds to the end of a file.
# 
# file - String path of file to add to
# text - text to add
# 
# Example
# 
#   appent_to_file 'path/to/file.rb', 'Hello, world!'
# 
# Returns nothing.
# 
# Todo
# 
#   - Return true/false based on success.
def append_to_file file, text
  File.open(file, 'a') {|f| f.write(text) }
end

# Public: Copies a file from one location to another.
# Asks the user of existing files should be overwritten.
# 
# orignal_file - String path of the file to be copied
#     new_file - Destination of the copied file
# 
# Example
# 
#   copy_file 'path/to/original_file.rb', 'path/to/new/location.rb'
# 
# Returns true if the file was copied, false if not.
def copy_file original_file, new_file
  unless File.exists? new_file
    puts LABELS[:add] + new_file
    FileUtils.cp original_file, new_file
    return true
  else
    if overwritable? new_file
      puts LABELS[:overwrite] + new_file
      FileUtils.cp original_file, new_file
      return true
    else
      puts LABELS[:ignore] + new_file
      return false
    end
  end
end

# Public: Copies a file using ERB to insert variables.
# 
# template_file - String path of the template to be copied
#      new_file - String path of the file to create from the template_file
#        locals - Hash of variables to pass to the temlate_file
# 
# Example
# 
#   copy_template "#{TEMPLATES}/path/to/template.rb",
#                 'path/to/new/file.rb',
#                 { foo: 'bar' }
# 
# Returns true if the template was copied, false if not.
def copy_template template_file, new_file, locals = {}
  unless File.exists? new_file
    puts LABELS[:add] + new_file
    File.open(new_file, 'w') { |f| f.write( ERB.new(File.read(template_file)).result(binding) ) }
    return true
  else
    if overwritable? new_file
      puts LABELS[:overwrite] + new_file
      File.open(new_file, 'w') { |f| f.write( ERB.new(File.read(template_file)).result(binding) ) }
      return true
    else
      puts LABELS[:ignore] + new_file
      return false
    end
  end
end

# Public: Creates a directory if it doesn't already exist.
# 
# *args - path(s) as a String, multiple Strings, or an Array of Strings
# 
# Examples
# 
#   create_directory 'path/to/directory'
#   create_directory 'path/to/directory', 'path/to/other/directory
#   create_directory ['path/to/directory', 'path/to/other/directory']
# 
# Returns nothing.
# 
# Todo
# 
#   - Return true/false based on success.
def create_directory *args
  args = args.first if args.first.kind_of? Array
  args.each { |dir| FileUtils.mkdir(dir) unless File.exists?(dir) }
end

# Public: Copies a directory (with contents) to another directory.
# If the new directory doesn't exist, it will be created.
# 
# original_dir - String path of the directory to be copied from
#      new_dir - String path of directory to be copied to
# 
# Example
# 
#   copy_directory 'path/to/original/directory', 'path/to/new/directory'
# 
# Returns nothing.
# 
# Todo
# 
#   - Return true/false based on success.
def copy_directory original_dir, new_dir
  create_directory new_dir
  Dir.glob("#{original_dir}/**/{*,.gitignore}").each do |path|
    new_path = path.sub original_dir, new_dir
    File.directory?(path) ? create_directory(new_path) : copy_file(path, new_path)
  end
end
